package com.cykj.order.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cykj.common.core.exception.ServiceException;
import com.cykj.common.core.utils.StringUtils;
import com.cykj.order.domain.BsOrders;
import com.cykj.order.domain.BsOrdersDetail;
import com.cykj.order.domain.dto.AlipayPageReqDTO;
import com.cykj.order.domain.dto.OrderCreateReqDTO;
import com.cykj.order.domain.dto.OrderItemReqDTO;
import com.cykj.order.mapper.BsOrdersDetailMapper;
import com.cykj.order.mapper.BsOrdersMapper;
import com.cykj.order.mapper.CtCartOperateMapper;
import com.cykj.order.service.OrderBusinessService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单业务服务实现
 */
@Service
public class OrderBusinessServiceImpl implements OrderBusinessService {

    // RocketMQ延迟级别：10分钟对应级别14
    private static final int ORDER_TIMEOUT_DELAY_LEVEL = 14;
    private static final String ROCKETMQ_TOPIC = "order-timeout-topic";
    private static final String REDIS_ORDER_LOCK_KEY = "order:notify:lock:"; // 支付回调幂等锁

    // 订单号前缀
    private static final String ORDER_NUMBER_PREFIX = "ORDER";
    // 用于生成订单号的计数器，每天重置
    private static final String REDIS_COUNTER_KEY = "order:number:counter:";

    @Autowired
    private BsOrdersMapper bsOrdersMapper;

    @Autowired
    private BsOrdersDetailMapper bsOrdersDetailMapper;

    @Autowired
    private CtCartOperateMapper ctCartOperateMapper;

    @Autowired
    @Qualifier("orderAlipayClient")
    private AlipayClient alipayClient;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 创建订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrder(OrderCreateReqDTO reqDTO) {
        // 1. 计算核心金额（避免前端篡改，后端重新计算）
        BigDecimal productAmount = BigDecimal.ZERO; // 商品原价总和
        for (OrderItemReqDTO item : reqDTO.getOrderItems()) {
            // 商品单价 * 数量 = 该商品总价
            BigDecimal itemTotal = item.getPrice().multiply(new BigDecimal(item.getQuantity()));
            productAmount = productAmount.add(itemTotal);
        }
        BigDecimal totalAmount = productAmount.add(reqDTO.getDeliveryFee()); // 订单总金额 = 商品总价 + 配送费

        // 2. 生成唯一订单号（后端生成，不再依赖前端）
        String orderNumber = generateUniqueOrderNumber();

        // 3. 构建BsOrders实体
        BsOrders bsOrders = new BsOrders();
        bsOrders.setOrderNumber(orderNumber); // 使用后端生成的订单号
        bsOrders.setUserId(reqDTO.getCustomerId());
        bsOrders.setShopId(reqDTO.getBusinessId());
        bsOrders.setTotalAmount(totalAmount);
        bsOrders.setProductAmount(productAmount);
        bsOrders.setDeliveryFee(reqDTO.getDeliveryFee());
        bsOrders.setRemark(reqDTO.getRemark());
        bsOrders.setStatus(0); // 初始状态：0=待支付
        bsOrders.setCreateTime(new Date());

        // 4. 插入订单
        bsOrdersMapper.insert(bsOrders);
        Long orderId = bsOrders.getId();

        // 5. 插入订单明细
        List<BsOrdersDetail> detailList = reqDTO.getOrderItems().stream().map(item -> {
            BsOrdersDetail detail = new BsOrdersDetail();
            detail.setOrderId(orderId);
            detail.setProductId(item.getProductId());
            detail.setQuantity(item.getQuantity());
            detail.setOriginalPrice(item.getPrice());
            detail.setActualPrice(item.getPrice());
            detail.setRefundStatus(0);
            detail.setCreateTime(new Date());
            return detail;
        }).collect(Collectors.toList());
        bsOrdersDetailMapper.batchInsert(detailList);

  /*      // 6. 发送订单超时消息（10分钟后检查订单状态）
        rocketMQTemplate.syncSend(ROCKETMQ_TOPIC, orderId);*/

        return orderId;
    }

    /**
     * 生成唯一订单号
     * 格式: ORDER + 年月日时分秒毫秒 + 3位计数器 + 2位随机数
     */
    private String generateUniqueOrderNumber() {
        // 获取当前时间戳（精确到毫秒）
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

        // 每天一个计数器，确保每天从1开始计数
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String counterKey = REDIS_COUNTER_KEY + date;

        // 自增计数器，确保同一毫秒内的唯一性
        Long count = redisTemplate.opsForValue().increment(counterKey, 1);
        // 设置过期时间，第二天自动失效
        redisTemplate.expire(counterKey, 24, TimeUnit.HOURS);

        // 生成2位随机数，进一步降低冲突概率
        String random = String.format("%02d", (int) (Math.random() * 100));

        // 拼接订单号
        return ORDER_NUMBER_PREFIX + timestamp + String.format("%03d", count) + random;
    }

    /**
     * 生成支付宝沙箱支付页面
     */
    @Override
    public String generateAlipayPage(AlipayPageReqDTO reqDTO) {
        // 校验订单状态（待支付）
        BsOrders order = bsOrdersMapper.selectById(reqDTO.getOrderId());
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        if (!order.getStatus().equals(0)) {
            throw new ServiceException("订单状态异常，无法支付");
        }

        //构建支付宝支付请求
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        // 支付宝异步回调地址
        request.setNotifyUrl("http://127.0.0.1:8080/order/alipay/notify");
        // 支付宝同步回调地址（前端，支付完成后跳转）
        request.setReturnUrl(reqDTO.getReturnUrl());

        // 封装支付参数
        String bizContent = String.format("{" +
                        "\"out_trade_no\":\"%s\"," +
                        "\"total_amount\":\"%s\"," +
                        "\"subject\":\"%s\"," +
                        "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"" +
                        "}",
                order.getOrderNumber(),
                order.getTotalAmount().setScale(2),
                "店铺[" + order.getShopId() + "]订单-" + order.getOrderNumber()
        );
        request.setBizContent(bizContent);

        // 调用支付宝SDK生成支付页面
        try {
            return alipayClient.pageExecute(request).getBody();
        } catch (AlipayApiException e) {
            throw new ServiceException("支付宝支付链接生成失败：" + e.getErrMsg());
        }
    }

    /**
     * 处理支付宝支付回调
     */
    @Override
    public String handleAlipayNotify(java.util.Map<String, String> paramMap) {
        // 1. 提取回调参数
        String outTradeNo = paramMap.get("out_trade_no");
        String tradeStatus = paramMap.get("trade_status");
        String totalAmount = paramMap.get("total_amount");

        // 2. 校验支付状态
        if (!"TRADE_SUCCESS".equals(tradeStatus)) {
            return "fail";
        }

        // 分布式锁防重复处理
        String lockKey = REDIS_ORDER_LOCK_KEY + outTradeNo;
        Boolean lockSuccess = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.MINUTES);
        if (Boolean.FALSE.equals(lockSuccess)) {
            return "success";
        }

        try {
            // 查询订单
            BsOrders order = bsOrdersMapper.selectOne(new LambdaQueryWrapper<BsOrders>()
                    .eq(BsOrders::getOrderNumber, outTradeNo));
            if (order == null) {
                return "fail";
            }

            if (!order.getStatus().equals(0)) {
                return "success";
            }

            if (!order.getTotalAmount().toString().equals(totalAmount)) {
                return "fail";
            }

            order.setStatus(1); // 1-已支付待接单
            order.setPayTime(new Date());
            order.setPaymentMethod(1); // 1-支付宝
            bsOrdersMapper.updateById(order);

            return "success";
        } catch (Exception e) {
            return "fail";
        }
    }

    /**
     * 超时取消订单
     */
    @Override
    public void cancelOrderByTimeout(Long orderId) {
        // 1. 查询订单
        BsOrders order = bsOrdersMapper.selectById(orderId);
        if (order == null) {
            return;
        }
        // 2. 仅待支付订单可取消
        if (!order.getStatus().equals(0)) {
            return;
        }
        // 3. 执行取消（更新状态为5-已取消）
        int updateCount = bsOrdersMapper.cancelOrderByTimeout(orderId, "订单超时未支付，系统自动取消");
        if (updateCount == 0) {
            throw new ServiceException("订单超时取消失败，orderId=" + orderId);
        }
    }
}
